import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.io.InputStream;
import java.io.OutputStream;

import com.iplusbot.api.Api;

public class App {
    private Socket sock;
    private ByteBuffer sizebuff;

    public App(String host, int port) throws Exception {
        sock = new Socket(host, port);
        sizebuff = ByteBuffer.allocate(4);
        sizebuff.order(ByteOrder.LITTLE_ENDIAN);
    }

    private Api.Response sendRequest(Api.Request req) throws Exception{
        Api.ApiMessage msg = Api.ApiMessage.newBuilder()
            .setType(Api.MessageType.MSG_REQ)
            .setReq(req)
            .build();

        // send
        OutputStream out = sock.getOutputStream();
        byte[] data = msg.toByteArray();
        sizebuff.clear();
        sizebuff.putInt(data.length);
        out.write(sizebuff.array());
        out.write(data);
        out.flush();

        // recv
        InputStream in = sock.getInputStream();
        sizebuff.clear();
        in.read(sizebuff.array(), 0, 4);
        int size = sizebuff.getInt();
        ByteBuffer buff = ByteBuffer.allocate(size);
        in.read(buff.array());

        Api.ApiMessage rmsg = Api.ApiMessage.parseFrom(buff.array());
        return rmsg.getResp();
    }

    public void queryRobotInfo(int ...args) throws Exception {
        Api.Request.Builder builder = Api.Request.newBuilder();
        builder.setType(Api.Request.RequestType.REQ_ROBOT_INFO);
        for (int i=0; i<args.length; i++) {
            builder.addRobotIds(args[i]);
        }
        Api.Request req = builder.build();
        Api.Response resp = sendRequest(req);
        System.out.println(resp);
    }

    public long createMission(String uuid, String mapname, int[] targets, String[] actions) throws Exception {
        Api.Mission.Builder builder = Api.Mission.newBuilder();
        builder.setRefUuid(uuid);
        builder.setPriority(3);
        for (int i=0; i<targets.length; i++) {
            Api.Mission.MissionStep s = Api.Mission.MissionStep.newBuilder()
                .setMapName(mapname)
                .setTarget(targets[i])
                .setAction(actions[i])
                .build();
            builder.addSteps(i, s);
        }

        Api.Mission m = builder.build();
        Api.Request req = Api.Request.newBuilder()
            .setType(Api.Request.RequestType.REQ_MISSION_NEW)
            .setMission(m)
            .build();
        Api.Response resp = sendRequest(req);
        System.out.println(resp);
        if (!resp.getOk()) {
            return 0;
        }
        return resp.getMission().getId();
    }

    public void queryMissionInfo(long mid) throws Exception {
        Api.Request req = Api.Request.newBuilder()
            .setType(Api.Request.RequestType.REQ_MISSION_INFO)
            .setMissionId(mid)
            .build();
        Api.Response resp = sendRequest(req);
        System.out.println(resp);
    }

    public void queryMissionInfoByUuid(String uuid) throws Exception {
        Api.Request req = Api.Request.newBuilder()
            .setType(Api.Request.RequestType.REQ_MISSION_INFO)
            .setMissionUuid(uuid)
            .build();
        Api.Response resp = sendRequest(req);
        System.out.println(resp);
    }

    public void cancelMission(String uuid) throws Exception {
        Api.MissionCommand cmd = Api.MissionCommand.newBuilder()
            .setMissionUuid(uuid)
            .setCmd(Api.MissionCommand.CommandType.MCMD_CANCEL)
            .build();
        Api.Request req = Api.Request.newBuilder()
            .setType(Api.Request.RequestType.REQ_MISSION_COMMAND_NEW)
            .setMscmd(cmd)
            .build();
        Api.Response resp = sendRequest(req);
        System.out.println(resp);
    }

    public static void main(String[] args) {
        int port = 8848;
        try {
            if (args.length > 0) {
                port = Integer.parseInt(args[0]);
            }
            System.out.printf("connect to server at %d\n", port);
            App app = new App("", port);
            app.queryRobotInfo();
            String uuid = "yyy-123";
            long mid = app.createMission(uuid, "test", new int[]{1,2,3}, new String[]{"load", "unload", "charge"});
            app.queryMissionInfo(mid);
            app.cancelMission(uuid);
            app.queryMissionInfoByUuid(uuid);
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
